package cn.zyjblogs.config.security.granter;

import cn.zyjblogs.server.user.dto.AuthorizationDto;
import cn.zyjblogs.starter.common.entity.constant.CommonRedisKeyConstant;
import cn.zyjblogs.starter.common.entity.response.HttpCode;
import cn.zyjblogs.starter.common.exception.AuthRuntimeException;
import cn.zyjblogs.starter.redis.utils.RedisTemplateHandler;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AbstractTokenGranter;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.util.StringUtils;

import java.util.Map;

public class SmsCodeTokenGranter extends AbstractTokenGranter {
    private static final String GRANT_TYPE = "smscode";
    private RedisTemplateHandler<String, String> redisTemplateHandler;

    private UserDetailsService userDetailsService;

    protected SmsCodeTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, String grantType) {
        super(tokenServices, clientDetailsService, requestFactory, grantType);
    }

    public SmsCodeTokenGranter(RedisTemplateHandler redisTemplateHandler, UserDetailsService userDetailsService, AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService
            , OAuth2RequestFactory requestFactory) {
        super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
        this.redisTemplateHandler = redisTemplateHandler;
        this.userDetailsService = userDetailsService;
    }

    @Override
    protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
        Map<String, String> requestParameters = tokenRequest.getRequestParameters();
        String username = requestParameters.get("username");
        String password = requestParameters.get("password");
        if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password)) {
            throw new AuthRuntimeException(HttpCode.BAD_REQUEST, "用户名或验证码不能为空");
        }
        String codeParams = redisTemplateHandler.get(CommonRedisKeyConstant.SMS_LOGIN + username);
        if (!StringUtils.hasLength(codeParams)) {
            throw new AuthRuntimeException(HttpCode.BAD_REQUEST, "验证码已过期");
        }
        if (!password.trim().equals(codeParams.split(",")[0])) {
            throw new AuthRuntimeException(HttpCode.BAD_REQUEST, "验证码不正确");
        }
        UserDetails userDetails = userDetailsService.loadUserByUsername(username);
        if (userDetails == null) {
            throw new AuthRuntimeException(HttpCode.BAD_REQUEST, "验证码该用户不存在");
        }
        AuthorizationDto authorization = new AuthorizationDto();
        authorization.setPrincipal(userDetails);
        authorization.setAuthenticated(true);
        OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);
        return new OAuth2Authentication(storedOAuth2Request, authorization);
    }
}
